package actions;


import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Vector;

import parameters.RLM_Parameters;

import utils.MessageViewer;
import client.ClientApplication;
import client.ClientSocketConnection;
import client.ClientUser;
import client_commands.SERV_ADDEDCommand;
import client_gui.ClientWindow;
import client_server.ClientServer;
import client_tree.User;


/**
 * Klasa koja predstavlja akciju Login dugmeta u startup panelu klijenta.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public class LoginAction extends RLMAbstractAction {


	/**
	 * Konstruktor.
	 * @param owner - vlasnik akcije
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public LoginAction(ClientWindow owner) {
		setActionOwner(owner);
//		putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0));
//		putValue(SMALL_ICON, loadIcon("images/logout.png"));
		putValue(NAME, "Login");
		putValue(SHORT_DESCRIPTION, "Login");
	}
	

	
	
	public void actionPerformed(ActionEvent e) {
		
		getActionOwner().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		
		// pokretanje servera ukoliko nije pokrenut
		if ( getActionOwner().getApplicaton().isClientServerRunning() == false ) {

			ClientServer clientServer = new ClientServer(getActionOwner().getApplicaton());			
	
			try {
				ClientApplication.clientServerSemaphore.acquire();
				
				getActionOwner().getApplicaton().setClientServer(clientServer);
			}
			catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		
		}
		
//		getActionOwner().getApplicaton().loadChatDialogParameters();
		

		// pocetak logovanja
		try {
			ClientApplication.loginSemaphore.acquire();
		}
		catch (InterruptedException e1) {
			e1.printStackTrace();
		}

		ClientWindow owner = getActionOwner();
		
		if ( owner.getApplicaton().createSocketConnection() == false ) {
			releaseSemaphores();
			getActionOwner().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			return;
		}

		ClientSocketConnection connection = owner.getApplicaton().retrieveSocketConnection();

//		getActionOwner().getApplicaton().setClientUser(null);	
//		owner.getApplicaton().setClientUser(new ClientUser());
		
		if (owner.getApplicaton().getClientUser() == null) {
			owner.getApplicaton().setClientUser(new ClientUser());
		}
		
		// ostatak LOGIN akcije
		
		if (owner.createPartialLoginInfo() == false) {
			releaseSemaphores();
			getActionOwner().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			return;
		}
		
		owner.getApplicaton().getClientUser().setFontName(owner.getFontName());
		owner.getApplicaton().getClientUser().setFontStyle(owner.getFontStyle());
		owner.getApplicaton().getClientUser().setFontSize(owner.getFontSize());
		owner.getApplicaton().getClientUser().setFontColor(owner.getFontColor());
		owner.getApplicaton().getClientUser().setBackgroundColor(owner.getBackgroundColor());
		
		connection.setUsername(owner.getApplicaton().getClientUser().getUsername());
		
		StringBuffer buffer = new StringBuffer();
		buffer.append("LOGIN ");
		buffer.append(owner.getApplicaton().getClientUser().getUsername());
		buffer.append(" ");
		buffer.append(owner.getApplicaton().getClientUser().getPassword());
		buffer.append(" ");
		buffer.append(STATUS_NAMES[owner.getApplicaton().getClientUser().getStatus()]);
		// ne treba - uzimace server automatski
//		buffer.append(" ");
//		buffer.append(owner.getApplicaton().getClientSideServerIP());
		
		// proba za detekciju lokalne konekcije
		buffer.append(" ");
		buffer.append(RLM_Parameters.getNetworkInterfaceToConnect(true));
		buffer.append(" ");
//		buffer.append(owner.getApplicaton().getClientSideServerPort());
		buffer.append(RLM_Parameters.getTcpPort());
		
		String completedLoginInfo = buffer.toString();
		
//		try {
//			Thread.sleep(200);
//			connection.semaphore.acquire();
//		}
//		catch (InterruptedException ie) {
//			ie.printStackTrace();
//		}
		
		connection.setMessage(LOGIN_CMD, completedLoginInfo);
		
		String response;
		
		response = connection.buffers[LOGIN_CMD].read();

		
		if (response.startsWith("210")) {
			MessageViewer.showError(getActionOwner(), "Bad username.");
			releaseSemaphores();
			getActionOwner().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			return;
		} else
		if (response.startsWith("220")) {
			MessageViewer.showError(getActionOwner(), "User already logged in.");
			releaseSemaphores();
			getActionOwner().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			return;
		} else
		if (response.startsWith("230")) {
			MessageViewer.showError(getActionOwner(), "Wrong password.");
			releaseSemaphores();
			getActionOwner().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			return;
		}
		
		ArrayList<Vector> contactList = null;
		ArrayList<String> blockList = null;
		
		if (response.startsWith("110")) {

			response = connection.buffers[LOGIN_CMD].read();
			
			Vector<String> parameters = new Vector<String>(getLoginResponse(response));
			
			owner.getApplicaton().getClientUser().setNickname(parameters.get(0));
			owner.getApplicaton().getClientUser().setEmail(parameters.get(1));
			owner.getApplicaton().getClientUser().setRegDate(parameters.get(2));
			owner.getApplicaton().getClientUser().setAvatar(parameters.get(3));
			owner.getApplicaton().getClientUser().setPublicIP(parameters.get(4));

			
			String contactListCommand = "CONT_LIST " + owner.getApplicaton().getClientUser().getUsername();

			connection.setMessage(LOGIN_CMD, contactListCommand);
			
			response = connection.buffers[LOGIN_CMD].read();
			
			if (response.startsWith("120")) {
				StringTokenizer tokens = new StringTokenizer(response);
				tokens.nextToken();
				tokens.nextToken();
				
				int rowCount = Integer.parseInt(tokens.nextToken());
				
				contactList = new ArrayList<Vector>();
				
				for (int i = 0; i < rowCount; i++) {
					response = connection.buffers[LOGIN_CMD].read();
					contactList.add(new Vector<String>(getContactListEntry(response)));
				}
			}
			
			String blockListCommand = "BLOCK_LIST " + owner.getApplicaton().getClientUser().getUsername();
			connection.setMessage(LOGIN_CMD, blockListCommand);
			
			response = connection.buffers[LOGIN_CMD].read();
			
			if (response.startsWith("130")) {
				StringTokenizer tokens = new StringTokenizer(response);
				tokens.nextToken();
				tokens.nextToken();
				
				int rowCount = Integer.parseInt(tokens.nextToken());
				
				blockList = new ArrayList<String>();
				
				for (int i = 0; i < rowCount; i++) {
					response = connection.buffers[LOGIN_CMD].read();
					blockList.add(response);
				}
			}
			
			// kreiranje modela podataka
			
			// ContactList
			for (int i = 0; i < contactList.size(); i++) {
				String username = contactList.get(i).get(0).toString();
				String nickname = contactList.get(i).get(1).toString();
				String email = contactList.get(i).get(2).toString();
				String ip_address = contactList.get(i).get(3).toString();
				String localAddress = contactList.get(i).get(4).toString();
				int port = Integer.parseInt(contactList.get(i).get(5).toString());
				String status = contactList.get(i).get(6).toString();
				String regDate = contactList.get(i).get(7).toString();
				String avatar = contactList.get(i).get(8).toString();
				
				User user = new User(username, nickname, email, ip_address, localAddress, port, status, regDate, avatar);
			
				getActionOwner().getApplicaton().getClientModel().addUser(user);

			}
			
					
			// BlockList
			for (int i = 0; i < blockList.size(); i++) {
				owner.getApplicaton().getClientUser().addToBlockList(blockList.get(i));
			}

			
			// setovanje avatara, nickname-a i statusa
			owner.setAvatar(owner.getApplicaton().getClientUser().getAvatar());
			owner.setNickname(owner.getApplicaton().getClientUser().getNickname());
			owner.setStatus(owner.getApplicaton().getClientUser().getStatus());
			
			
			// setovanje stanja client aplikacije
			getActionOwner().getApplicaton().setState(LOGGED_STATE);
			getActionOwner().setTrayIcon(owner.getApplicaton().getClientUser().getStatus());
			
			
			// osvezavanje prozora aplikacije
			getActionOwner().refreshWindow();
			
			
			// preuzimanje off aktivnosti (add_message)
			String addMsgsListCommand = "ADD_MSGS " + owner.getApplicaton().getClientUser().getUsername();

			connection.setMessage(LOGIN_CMD, addMsgsListCommand);
			
			response = connection.buffers[LOGIN_CMD].read();
			
			Vector<String> addMsgsList = new Vector<String>();
			
			if ( response.startsWith("140") ) {
				StringTokenizer tokens = new StringTokenizer(response);
				tokens.nextToken();
				tokens.nextToken();
				
				int rowCount = Integer.parseInt(tokens.nextToken());
				
				for (int i = 0; i < rowCount; i++) {
					response = connection.buffers[LOGIN_CMD].read();
					addMsgsList.add(response);
				}
			}
			
			
			for (int i = 0; i < addMsgsList.size(); i++) {
				
				StringBuffer servAddParameters = new StringBuffer();
				servAddParameters.append(owner.getApplicaton().getClientUser().getUsername());
				servAddParameters.append(" ");
				
				servAddParameters.append(addMsgsList.get(i));
				
				SERV_ADDEDCommand command = new SERV_ADDEDCommand(servAddParameters.toString());
				
				command.executeCommand(owner.getApplicaton());
			}
		}
			
		releaseSemaphores();
		
		getActionOwner().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}
	
	
	
	/**
	 * Metod parsira jedan red kontakt liste, i parsirane podatke smesta u Vector
	 * koji se vraca iz metode.
	 * Ocekivani podaci:
	 * username, nickname, email, ip_address, port, status, reg_date, avatar
	 * @param data - string koji predstavlja jedan red kontakt liste, tj. jednog user-a
	 * @return - parsirani podaci koji predstavljaju user-a u kontakt listi
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private Vector<String> getContactListEntry(String data) {
		Vector<String> entry = new Vector<String>();
		
		StringTokenizer tokens = new StringTokenizer(data);
		
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		entry.add(tokens.nextToken());
		
		return entry;
	}
	
	
	
	/**
	 * Metoda parsira prvi odgovor servera na komandu LOGIN.
	 * Ocekuju se sledeci podaci: nickname, email, reg_date, avatar.
	 * @param data - odgovor od servera
	 * @return - Vector sa parsiranim podacima
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private Vector<String> getLoginResponse(String data) {
		
		Vector<String> parameters = new Vector<String>();
		
		StringTokenizer tokens = new StringTokenizer(data);
		
		parameters.add(tokens.nextToken());
		parameters.add(tokens.nextToken());
		parameters.add(tokens.nextToken());
		parameters.add(tokens.nextToken());
		parameters.add(tokens.nextToken());
		
		return parameters;
	}

	
	private void releaseSemaphores() {
		ClientApplication.clientServerSemaphore.release();
		ClientApplication.loginSemaphore.release();
	}
	
}
